package Threads.ReentrantLock.abcabcabc;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;



//使用reentrantlock的情况下
//两种方式实现循环打印abc

public class lcok_condition {
    public static void main(String[] args) {
        Sync sync=new Sync(new ReentrantLock(),5);
        final ReentrantLock as = sync.getLock();

        Condition aWaitSet = as.newCondition();
        Condition bWaitSet = as.newCondition();
        Condition cWaitSet = as.newCondition();

       /* new Thread(() -> {
            sync.print("a", aWaitSet, bWaitSet);
        }).start();
        new Thread(() -> {
            sync.print("b", bWaitSet, cWaitSet);
        }).start();
        new Thread(() -> {
            sync.print("c", cWaitSet, aWaitSet);
        }).start();


        //signal the aWaitSet and start the loop
        try {
            as.lock();
            aWaitSet.signal();
        }finally {
            as.unlock();
        }*/
        sync.setFlag(1);
        new Thread(() -> {
            sync.print2("a", aWaitSet, bWaitSet,1,2);
        }).start();
        new Thread(() -> {
            sync.print2("b", bWaitSet, cWaitSet,2,3);
        }).start();
        new Thread(() -> {
            sync.print2("c", cWaitSet, aWaitSet,3,1);
        }).start();

    }
    static class Sync{
        private ReentrantLock lock=new ReentrantLock();
        private int loopCount;
        private int flag;

        public Sync(ReentrantLock lock,int loopCount){
            this.lock=lock;
            this.loopCount=loopCount;
        }

        public ReentrantLock getLock() {
            return lock;
        }

        public void setFlag(int flag) {
            this.flag = flag;
        }

        public void print(String str, Condition c1, Condition c2) {
            for (int i=0;i<loopCount;i++){
                lock.lock();
                try {
                    c1.await();
                    System.out.println(str);
                    c2.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }

            }
        }

        public void print2(String str, Condition c1, Condition c2,int flag,int nflag) {
            for (int i=0;i<loopCount;i++){
                lock.lock();
                try {
                    while (this.flag!=flag)
                        c1.await();
                    System.out.println(str);
                    this.flag=nflag;
                    c2.signal();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    lock.unlock();
                }

            }
        }
    }
}
